#!/usr/bin/env python

import pdb
from threading import Thread
from config import TestCaseManager
from nor_socket import Server
from serialport_socket import SerialPortServer
from map_table import MapTableManager


Blacktea_Map_Table = [
	{"command":"press",
 		"condition_list":{},
 		"output_list":[],
 		"default_output":"START_OK\r"},
	{"command":"release",
 		"condition_list":{},
 		"output_list":[],
 		"default_output":"OK\r"},
 	{"command":"default",
 		"condition_list":{},
 		"output_list":[],
 		"default_output":"ERR\r"},
]


class SerialPortServerWrapper(Thread):
	"""A echo server for Serialport. It will be used to cheaten TM.
	"""
	def __init__(self,baudrate,map_table=Blacktea_Map_Table):
		super(SerialPortServerWrapper, self).__init__()
		self.server_ = SerialPortServer(baudrate=baudrate)
		self.map_table_ = MapTableManager(map_table = map_table)
		# Set thread as a Daemon thread. Once all of normal thread exit,
		# Daemon thread will crash instantly without any terminate process.
		# This will cause that some resources isn't released.
		self.setDaemon(True)

	def run(self):
		try:
			while self.server_.isOpen():
				requ_str = self.server_.recv()
				if requ_str=="":
					break
				print("\r\n\r\nRecv from Serialport > {0}".format(requ_str))
				resp_str = self.map_table_.getResponseString(requ_str)
				print("Send to serialport > {0}".format(resp_str))
				self.server_.send(resp_str)
		finally:
			self.server_.close()



class ServerWrapper(Thread):
	def __init__(self,ip,port,map_table=None,base_id_regex=None):
		super(ServerWrapper, self).__init__()
		self.ip_ = ip
		self.port_ = port
		self.server_ = Server(ip=ip,port=port)
		self.map_table_ = None
		if map_table!=None:
			self.setMapTable(map_table=map_table, base_id_regex=base_id_regex)
		# Set thread as a Daemon thread. Once all of normal thread exit,
		# Daemon thread will crash instantly without any terminate process.
		# This will cause that some resources isn't released.
		self.setDaemon(True) 

	def setMapTable(self,map_table,base_id_regex):
		# TODO : Add  asynchronous control for critical variable.
		print("Update map table for {0}:{1}".format(self.ip_,self.port_))
		self.map_table_ = MapTableManager(map_table = map_table,base_id_regex=base_id_regex)

	def run(self):
		while True:
			print("waiting for new connection at {0}:{1}.".format(self.ip_,self.port_))
			self.server_.accept()
			try:
				print("client connected.")
				while True:
					requ_str = self.server_.recv()
					if requ_str=="":
						break
					print("\r\n\r\nRecv from {0}:{1}> {2}".format(self.ip_,self.port_,requ_str))
					resp_str = self.map_table_.getResponseString(requ_str)
					print("Send to {0}:{1} > {2}".format(self.ip_,self.port_,resp_str))
					self.server_.send(resp_str)
			finally:
				self.server_.close_client()


class DataCenter(object):
	# TODO: Redundancy Code.
	def buildServer_(self,ip_list,port_list):
		# for ip in slave_ip_list:
		# 	for port in slave_port_list:
		# 		server = ServerWrapper(ip,port)
		# 		sn = self.computeObjID(server.getSock())
		# 		# TODO FIX ME:
		# 		self.inputs_.append(server.getSock())
		# 		self.server_list_.append(server)
		arm_port = port_list["arm_port"]
		power_port = port_list["power_port"]
		dut_port = port_list["dut_port"]
		self.uut1_arm_server_ = ServerWrapper(ip=ip_list[0],port=arm_port)
		self.uut1_power_server_ = ServerWrapper(ip=ip_list[0],port=power_port)
		self.uut1_dut_server_ = ServerWrapper(ip=ip_list[0],port=dut_port)
		self.uut2_arm_server_ = ServerWrapper(ip=ip_list[1],port=arm_port)
		self.uut2_power_server_ = ServerWrapper(ip=ip_list[1],port=power_port)
		self.uut2_dut_server_ = ServerWrapper(ip=ip_list[1],port=dut_port)
		self.blacktea_server_ = SerialPortServerWrapper(baudrate=115200)


	def __init__(self,server_ip_list,server_port_list):
		super(DataCenter, self).__init__()
		# Build slave Server
		self.buildServer_(server_ip_list,server_port_list)


	def setMapTable(self,arm_mtable,power_mtable,dut_mtable,base_id_regex):
		self.uut1_arm_server_.setMapTable(arm_mtable,base_id_regex)
		self.uut1_power_server_.setMapTable(power_mtable,base_id_regex)
		self.uut1_dut_server_.setMapTable(dut_mtable,base_id_regex)
		self.uut2_arm_server_.setMapTable(arm_mtable,base_id_regex)
		self.uut2_power_server_.setMapTable(power_mtable,base_id_regex)
		self.uut2_dut_server_.setMapTable(dut_mtable,base_id_regex)


	def launchServer(self):
		print("Begin to launch fixture service thread...")
		self.uut1_arm_server_.start()
		self.uut1_power_server_.start()
		self.uut1_dut_server_.start()
		self.uut2_arm_server_.start()
		self.uut2_power_server_.start()
		self.uut2_dut_server_.start()
		self.blacktea_server_.start()
		print("Launch dummy fixture finish.")

	def run(self):
		self.launchServer()
		#self.fixture_thread_.join()
		while True: sleep(1)

